package com.lineage.server.datatables;

import com.lineage.DatabaseFactory;
import com.lineage.server.model.L1Spawn;
import com.lineage.server.templates.L1Npc;
import com.lineage.server.templates.L1QuestMobSpawn;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class QuesttSpawnTable {
  private static final Log _log = LogFactory.getLog(QuesttSpawnTable.class);
  
  private static QuesttSpawnTable _instance;
  
  private static final Map<Integer, L1Spawn> _spawntable = new HashMap<>();
  
  private static final Map<Integer, L1QuestMobSpawn> _spawntable_X1 = new HashMap<>();
  
  public static QuesttSpawnTable get() {
    if (_instance == null)
      _instance = new QuesttSpawnTable(); 
    return _instance;
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    int spawnCount = 0;
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT * FROM `server_quest_spawn`");
      rs = pstm.executeQuery();
      while (rs.next()) {
        int id = rs.getInt("id");
        int questid = rs.getInt("questid");
        boolean is_spawn = rs.getBoolean("is_spawn");
        int npc_templateid = rs.getInt("npc_templateid");
        L1Npc template1 = NpcTable.get().getTemplate(npc_templateid);
        if (template1 == null) {
          _log.error("召唤NPC编号: " + npc_templateid + " 不存在资料库中!(server_quest_spawn)");
          delete(npc_templateid);
          continue;
        } 
        if (!is_spawn) {
          int i = rs.getInt("count");
          int j = rs.getInt("group_id");
          int k = rs.getInt("locx1");
          int m = rs.getInt("locx2");
          int n = rs.getInt("locy1");
          int i1 = rs.getInt("locy2");
          int i2 = rs.getInt("mapid");
          int i3 = rs.getInt("heading");
          L1QuestMobSpawn mobSpawn = new L1QuestMobSpawn();
          mobSpawn.set_questid(questid);
          mobSpawn.set_count(i);
          mobSpawn.set_npc_templateid(npc_templateid);
          mobSpawn.set_group_id(j);
          mobSpawn.set_locx1(k);
          mobSpawn.set_locy1(n);
          mobSpawn.set_locx2(m);
          mobSpawn.set_locy2(i1);
          mobSpawn.set_heading(i3);
          mobSpawn.set_mapid(i2);
          mobSpawn.set_round(rs.getInt("round"));
          _spawntable_X1.put(Integer.valueOf(id), mobSpawn);
          continue;
        } 
        if (QuestTable.get().getTemplate(questid) == null)
          continue; 
        int count = rs.getInt("count");
        if (count == 0)
          continue; 
        int group_id = rs.getInt("group_id");
        int locx1 = rs.getInt("locx1");
        int locx2 = rs.getInt("locx2");
        int locy1 = rs.getInt("locy1");
        int locy2 = rs.getInt("locy2");
        int mapid = rs.getInt("mapid");
        int heading = rs.getInt("heading");
        int respawn_delay = rs.getInt("respawn_delay");
        int movement_distance = rs.getInt("movement_distance");
        int spawntype = rs.getInt("avoid_pc");
        if (locx1 == 0 && locx2 == 0 && locy1 == 0 && locy2 == 0)
          continue; 
        L1Spawn spawnDat = new L1Spawn(template1);
        spawnDat.setId(id);
        spawnDat.setAmount(count);
        spawnDat.setGroupId(group_id);
        if (locx2 == 0 && locy2 == 0) {
          spawnDat.setLocX(locx1);
          spawnDat.setLocY(locy1);
          spawnDat.setLocX1(0);
          spawnDat.setLocY1(0);
          spawnDat.setLocX2(0);
          spawnDat.setLocY2(0);
        } else {
          spawnDat.setLocX(locx1);
          spawnDat.setLocY(locy1);
          spawnDat.setLocX1(locx1);
          spawnDat.setLocY1(locy1);
          spawnDat.setLocX2(locx2);
          spawnDat.setLocY2(locy2);
        } 
        if (count > 1 && spawnDat.getLocX1() == 0) {
          int range = Math.min(count * 6, 20);
          spawnDat.setLocX1(spawnDat.getLocX() - range);
          spawnDat.setLocY1(spawnDat.getLocY() - range);
          spawnDat.setLocX2(spawnDat.getLocX() + range);
          spawnDat.setLocY2(spawnDat.getLocY() + range);
        } 
        if (locx2 < locx1 && locx2 != 0) {
          _log.error("server_quest_spawn : locx2 < locx1: " + id);
          continue;
        } 
        if (locy2 < locy1 && locy2 != 0) {
          _log.error("server_quest_spawn : locy2 < locy1: " + id);
          continue;
        } 
        spawnDat.setRandomx(0);
        spawnDat.setRandomy(0);
        spawnDat.setMinRespawnDelay(respawn_delay);
        spawnDat.setMovementDistance(movement_distance);
        spawnDat.setHeading(heading);
        spawnDat.setMapId((short)mapid);
        spawnDat.setSpawnType(spawntype);
        spawnDat.setTime(SpawnTimeTable.getInstance().get(spawnDat.getId()));
        spawnDat.setName(template1.get_name());
        spawnDat.init();
        spawnCount += spawnDat.getAmount();
        _spawntable.put(new Integer(spawnDat.getId()), spawnDat);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    _log.info("载入召唤QUEST NPC资料数量: " + spawnCount + "(" + timer.get() + "ms)");
  }
  
  public static void delete(int npc_id) {
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("DELETE FROM `server_quest_spawn` WHERE `npc_templateid`=?");
      ps.setInt(1, npc_id);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  public L1Spawn getTemplate(int id) {
    return _spawntable.get(new Integer(id));
  }
  
  public ArrayList<L1QuestMobSpawn> getMobSpawn(int questid) {
    ArrayList<L1QuestMobSpawn> spawnList = new ArrayList<>();
    Iterator<L1QuestMobSpawn> iterator = _spawntable_X1.values().iterator();
    while (iterator.hasNext()) {
      L1QuestMobSpawn mobSpawn = iterator.next();
      if (mobSpawn.get_questid() == questid)
        spawnList.add(mobSpawn); 
    } 
    return spawnList;
  }
}
